#include <windower.h>
/*======= window functions ==========*/
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327950288
#endif
inline double initDsp_lcSinc(double x)
{
	double y = M_PI * x;
	return sin(y)/(y);
}
/* sinc function : (sin x) / x  */
inline double initDsp_sinc(double x)
{
  return sin(x)/(x);
}

/* rectangular window */
double * initDsp_winRec(long _N)
{
	int i;
	double * ret = (double *)malloc(sizeof(double)*_N);
	double * x = ret;
	for (i=0; i<_N; i++) {
		*x = 1.0; x++;
	}
	return ret;
}

/* triangular window (non-zero endpoints) */
double * initDsp_winTri(long _N)
{
	long i;
	double * ret = (double *)malloc(sizeof(double)*_N);
	double * x = ret;
	for (i=0; i<_N/2; i++) {
		*x = 2.0*(double)(i+1)/(double)_N;
		x++;
	}
	for (i=_N/2; i<_N; i++) {
		*x = 2.0*(double)(_N-i)/(double)_N;
		x++;
	}
	return ret;
}

/* powered triangular window (non-zero endpoints) */
double * initDsp_winTrP(long _N)
{
	double *w = initDsp_winTri(_N);
	double *x = w;
	long n; for (n=0; n<_N; n++) *x = *x * (*(x++));
	return w;
}

/* bartlett (triangular) window (zero endpoints) */
double * initDsp_winBar(long _N)
{
	long i;
	double * ret = (double *)malloc(sizeof(double)*_N);
	double * x = ret;
	for (i=0; i<_N/2; i++) {
		*x = 2.0*(double)(i)/(double)(_N-1);
		x++;
	}
	for (i=_N/2; i<_N; i++) {
		*x = 2.0*(double)(_N-1-i)/(double)(_N-1);
		x++;
	}
	return ret;
}

/* hann(ing) window */
double * initDsp_winHan(long _N)
{
	double i;
	double * ret = (double *)malloc(sizeof(double)*_N);
	double * x = ret;
	double NN = (double)_N;
	for (i=0.0; i<NN; i += 1.0) {
		*x = 0.5*(1.0-cos( (2.0*M_PI*i)/(NN-1.0) ));
		x++;
	}
	return ret;
}

/* hamming window */
double * initDsp_winHam(long _N)
{
	double i;
	double * ret = (double *)malloc(sizeof(double)*_N);
	double * x = ret;
	double NN = (double)_N;
	for (i=0.0; i<NN; i += 1.0) {
		/*    *x = 0.53836 - 0.46164 * cos( (2.0*M_PI*i)/(NN-1.0) ); */
		*x = 0.54 - 0.46 * cos( (2.0*M_PI*i)/(NN-1.0) );
		x++;
	}
	return ret;
}

/* half-wave sine window (cosine window) */
double * initDsp_winSin(long _N)
{
	double i;
	double * ret = (double *)malloc(sizeof(double)*_N);
	double * x = ret;
	double NN = (double)_N;
	for (i=0.0; i<NN; i += 1.0) {
		*x = sin( (1.0*M_PI*i)/(NN-1.0) );
		x++;
	}
	return ret;
}

/* Lanczos window */
double * initDsp_winLac(long _N)
{
	double i;
	double * ret = (double *)malloc(sizeof(double)*_N);
	double * x = ret;
	double NN = (double)_N;
	for (i=0.0; i<NN; i += 1.0) {
		*x = initDsp_lcSinc( (2.0*i)/(NN-1.0) - 1.0 );
		x++;
	}
	return ret;
}

/* gaussian window ...??? */
double * initDsp_winGau(long _N, double sigma)
{
	double i;
	double * ret = (double *)malloc(sizeof(double)*_N);
	double * x = ret;
	double NN = (double)_N;
	double tmp;
	if (sigma <= 0.0) sigma = 0.01;
	if (sigma > 0.5) sigma = 0.5;
	for (i=0.0; i<NN; i += 1.0) {
		tmp = (i-(NN-1.0)/2.0)/(sigma*(NN-1.0)/2.0);
		*x = exp( -0.5 * ( tmp*tmp ) );
		x++;
	}
	return ret;
}

/* Blackman window */
double * initDsp_winBla(long _N, double alpha0, double alpha1, double alpha2)
{
	double i;
	double * ret = (double *)malloc(sizeof(double)*_N);
	double * x = ret;
	double NN = (double)_N;
	double tmp;
	for (i=0.0; i<NN; i += 1.0) {
		tmp = (2.0*M_PI*i)/(NN-1.0);
		*x = alpha0 - alpha1 * cos( tmp ) + alpha2 * cos( 2.0*tmp );
		x++;
	}
	return ret;

}

/* Bartlett-Hann window */
double * initDsp_winBaH(long _N, double alpha0, double alpha1, double alpha2)
{
	double i;
	double * ret = (double *)malloc(sizeof(double)*_N);
	double * x = ret;
	double NN = (double)_N;
	for (i=0.0; i<NN; i += 1.0) {
		*x = alpha0 - alpha1 * fabs( i/(NN-1.0) - 0.5 ) - alpha2 * cos( (2.0*M_PI*i)/(NN-1.0) );
		x++;
	}
	return ret;
}

/* Blackman-Harris window */
double * initDsp_winBlH(long _N, double alpha0, double alpha1, double alpha2, double alpha3)
{
	double i;
	double * ret = (double *)malloc(sizeof(double)*_N);
	double * x = ret;
	double NN = (double)_N;
	double tmp;
	for (i=0.0; i<NN; i += 1.0) {
		tmp = (2.0*M_PI*i)/(NN-1.0);
		*x = alpha0 - alpha1 * cos( tmp ) + alpha2 * cos( 2.0*tmp ) - alpha3 * cos( 3.0*tmp );
		x++;
	}
	return ret;
}

/****** other dsp functions *******/

/* compute harmonic product spectrum from a linear scale magnitude spectrum, use up to maxMul down-scaled spectra */
long initDsp_harmonicProductLin(const FLOAT_DMEM *src, long Nsrc, FLOAT_DMEM *dst, long Ndst, int maxMul)
{
	long i; int m;
	long oLen = Ndst;
	if (Nsrc < oLen) oLen = Nsrc;
	for (i=0; i<oLen; i++) {
		dst[i] = src[i];
		for (m=2; m<=maxMul; m++) {
			long idx = i*m;
			if (idx < Nsrc) dst[i] *= src[idx];
		}
	}
	return oLen;
}

/* compute harmonic sum spectrum from a linear scale magnitude spectrum, use up to maxMul down-scaled spectra */
long initDsp_harmonicSumLin(const FLOAT_DMEM *src, long Nsrc, FLOAT_DMEM *dst, long Ndst, int maxMul)
{
	long i; int m;
	long oLen = Ndst;
	if (Nsrc < oLen) oLen = Nsrc;
	for (i=0; i<oLen; i++) {
		dst[i] = src[i];
		for (m=2; m<=maxMul; m++) {
			long idx = i*m;
			if (idx < Nsrc) dst[i] += src[idx]/(FLOAT_DMEM)m;
		}
	}
	return oLen;
}
// a derived class should override this method, in order to implement the actual processing
	void cWindower::processFramer(cVector *_vec,cVector *_out) // idxi=input field index
{
	if (win != NULL) {
		double *w = win;
		long n;
		for (n=0; n<_vec->N; n++) {
			_out->dataF[n] = _vec->dataF[n] * (FLOAT_DMEM)(*(w++))/* + (FLOAT_DMEM)offset; src++; dst++*/; 
		}
	}
}

cWindower::cWindower(/*long _N*/)
{
	this->win =  initDsp_winHan(samplePerFrame); // Chon loai loc
}


cWindower::~cWindower()
{
	if(this->win != NULL)free(this->win);
}
